package com.example.demo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.demo.dao.OrderInfoMapper;
import com.example.demo.dao.OrderItemAddonRelationMapper;
import com.example.demo.dao.OrderItemMapper;
import com.example.demo.dao.OrderMainMapper;
import com.example.demo.dao.ProductBaseAddonRelationMapper;
import com.example.demo.dao.ProductMapper;
import com.example.demo.dao.ProductSkuMapper;
import com.example.demo.dao.ShopMapper;
import com.example.demo.domain.app.dto.ProductAddonDTO;
import com.example.demo.domain.app.param.GoodsAdditionParam;
import com.example.demo.domain.app.param.OrderItemParam;
import com.example.demo.domain.app.param.OrderSubmitParam;
import com.example.demo.domain.app.vo.OrderAmountSummaryVO;
import com.example.demo.domain.entity.OrderInfoDO;
import com.example.demo.domain.entity.OrderItemAddonRelation;
import com.example.demo.domain.entity.OrderItemDO;
import com.example.demo.domain.entity.OrderMainDO;
import com.example.demo.domain.entity.ProductDO;
import com.example.demo.domain.entity.ProductSkuDO;
import com.example.demo.domain.entity.ShopDO;
import com.example.demo.exception.BizException;
import com.example.demo.exception.ErrorConstants;
import com.example.demo.service.OrderService;
import com.example.demo.util.OrderIdGenerator;
import com.example.demo.util.SpecJsonUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMainMapper orderMainMapper;

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private OrderItemAddonRelationMapper orderItemAddonRelationMapper;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    @Autowired
    private ProductBaseAddonRelationMapper productBaseAddonRelationMapper;


    /**
     * 计算订单金额汇总（纯计算，无副作用）
     * 注意：此处逻辑必须与 create() 中的金额计算完全一致（包括潜在 bug）
     */
    // ==================== 对外接口 ====================
    @Override
    public OrderAmountSummaryVO preview(OrderSubmitParam param) {
        List<OrderItemParam> orderItemList = JSON.parseArray(param.getGoodsJsonStr(), OrderItemParam.class);
        if (CollectionUtils.isEmpty(orderItemList)) {
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "商品列表为空");
        }
        OrderCalcContext ctx = prepareOrderContext(orderItemList);
        return calculateAmount(ctx);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderAmountSummaryVO create(OrderSubmitParam param) {
        List<OrderItemParam> orderItemList = JSON.parseArray(param.getGoodsJsonStr(), OrderItemParam.class);
        if (CollectionUtils.isEmpty(orderItemList)) {
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "商品列表为空");
        }
        JSONObject jsonObject = JSON.parseObject(param.getExtJsonStr());
        String name = jsonObject.getString("联系人");
        String phone = jsonObject.getString("联系电话");
        // ========== 1. 生成主订单号 ==========
        String mainOrderNo = OrderIdGenerator.generateMainOrderNo();
        Long userId = StpUtil.getLoginIdAsLong();

        // ========== 2. 创建主订单 ==========
        OrderMainDO orderMain = new OrderMainDO();
        orderMain.setMainOrderNo(mainOrderNo);
        orderMain.setUserId(userId);
        orderMain.setTotalQuantity(0);
        orderMain.setTotalActualAmount(BigDecimal.ZERO);
        // 硬编码地址信息（根据你的原始代码）
        orderMain.setConsignee(name);
        orderMain.setPhone(phone);
        orderMain.setAddressDetail("关南社区");
        orderMain.setProvince("湖北省");
        orderMain.setCity("武汉市");
        orderMain.setDistrict("东湖高新区");
        orderMain.setPostalCode("438000");
        orderMain.setRemark("备注");
        orderMain.setInvoiceNeeded(1);
        orderMain.setInvoiceTitle("武汉市烽火集团有限公司");
        orderMain.setInvoiceTaxNo("91310101MA1FPX1234");
        orderMain.setCreatedFromCart(0);
        orderMain.setStatus(0);
        orderMain.setStatusDesc("待支付");
        orderMain.setPaymentMethod("线下支付");
        orderMain.setPayStatus(0);
        orderMainMapper.insert(orderMain);

        // ========== 3. 准备上下文（用于后续写库 + 金额计算一致性）==========
        OrderCalcContext ctx = prepareOrderContext(orderItemList);
        Map<Long, OrderItemParam> itemParamMap = orderItemList.stream().collect(Collectors.toMap(OrderItemParam::getGoodsId, Function.identity(), (x, y) -> x));

        BigDecimal totalActualAmount = BigDecimal.ZERO;
        int allTotalQuantity = 0;

        // ========== 4. 按店铺拆分子订单 ==========
        for (Map.Entry<Long, List<ProductDO>> entry : ctx.productGroupByShop.entrySet()) {
            Long shopId = entry.getKey();
            String subOrderNo = OrderIdGenerator.generateSubOrderNo();

            OrderInfoDO orderInfo = new OrderInfoDO();
            orderInfo.setOrderNo(subOrderNo);
            orderInfo.setMainOrderNo(mainOrderNo);
            orderInfo.setUserId(userId);
            orderInfo.setShopId(shopId);
            orderInfo.setShopName(ctx.shopMap.get(shopId).getName());
            orderInfo.setStatus(0);
            orderInfo.setStatusDesc("待支付");
            orderInfo.setTotalAmount(BigDecimal.ZERO);
            orderInfo.setActualAmount(BigDecimal.ZERO);
            orderInfo.setTotalQuantity(0);
            orderInfo.setDiscountAmount(BigDecimal.ZERO);
            orderInfo.setDeliveryFee(BigDecimal.ZERO);
            orderInfo.setPaymentMethod("线下付款");
            // 地址信息复制
            orderInfo.setConsignee(orderMain.getConsignee());
            orderInfo.setPhone(orderMain.getPhone());
            orderInfo.setAddressDetail("关南社区");
            orderInfo.setProvince("湖北省");
            orderInfo.setCity("武汉市");
            orderInfo.setDistrict("东湖高新区");
            orderInfo.setPostalCode("438000");
            orderInfo.setRemark("备注");
            orderInfo.setInvoiceNeeded(1);
            orderInfo.setInvoiceTitle("武汉市烽火集团有限公司");
            orderInfo.setInvoiceTaxNo("91310101MA1FPX1234");
            orderInfo.setCreatedFromCart(0);
            orderInfo.setLogisticsCompany("顺丰快递");
            orderInfo.setTrackingNo("SF123456789012");
            orderInfoMapper.insert(orderInfo);

            BigDecimal totalAmount = BigDecimal.ZERO;
            int totalQuantity = 0;

            for (ProductDO product : entry.getValue()) {
                OrderItemParam orderItemParam = itemParamMap.get(product.getId());
                String propertyChildIds = orderItemParam.getPropertyChildIds();

                List<ProductSkuDO> skus = ctx.skuMap.get(product.getId());
                ProductSkuDO matchedSku = skus.stream().filter(sku -> SpecJsonUtils.equalsIgnoreOrder(sku.getSpecJson(), propertyChildIds)).findFirst().orElse(skus.get(0));

                OrderItemDO orderItemDO = new OrderItemDO();
                orderItemDO.setOrderId(orderInfo.getId());
                orderItemDO.setProductId(product.getId());
                orderItemDO.setProductName(product.getName());
                orderItemDO.setSkuId(matchedSku.getId());
                orderItemDO.setSkuDesc(matchedSku.getSpecText());
                orderItemDO.setPicUrl(matchedSku.getPic());
                orderItemDO.setQuantity(orderItemParam.getNumber());
                orderItemDO.setUnitPrice(matchedSku.getSalePrice());
                orderItemDO.setAddonAmount(BigDecimal.ZERO);

                BigDecimal subtotal = orderItemDO.getUnitPrice().multiply(BigDecimal.valueOf(orderItemDO.getQuantity()));
                BigDecimal totalPrice = subtotal.setScale(2, RoundingMode.HALF_UP);
                orderItemDO.setTotalPrice(totalPrice);
                orderItemMapper.insert(orderItemDO);

                // 处理附加项
                List<GoodsAdditionParam> goodsAdditionList = orderItemParam.getGoodsAdditionList();
                if (CollectionUtils.isNotEmpty(goodsAdditionList)) {
                    List<Long> ids = goodsAdditionList.stream().map(GoodsAdditionParam::getId).collect(Collectors.toList());
                    List<OrderItemAddonRelation> relations = ctx.addonMap.get(product.getId()).stream().filter(f -> ids.contains(f.getAddonValueId())).map(m -> {
                        OrderItemAddonRelation r = new OrderItemAddonRelation();
                        r.setOrderItemId(orderItemDO.getId());
                        r.setAddonValueId(m.getAddonValueId());
                        r.setAddonOptionName(m.getAddonOptionName());
                        r.setAddonValueName(m.getAddonValueName());
                        r.setAddonPrice(m.getAddonPrice());
                        return r;
                    }).distinct().collect(Collectors.toList());

                    orderItemAddonRelationMapper.insertBatch(relations);

                    BigDecimal addonAmount = relations.stream().map(OrderItemAddonRelation::getAddonPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

                    // ⚠️ 这里必须与 calculateAmount 中逻辑一致！
                    BigDecimal pricePerUnit = orderItemDO.getUnitPrice().add(addonAmount); // 错误但一致
                    BigDecimal newTotalPrice = pricePerUnit.multiply(BigDecimal.valueOf(orderItemDO.getQuantity())).setScale(2, RoundingMode.HALF_UP);

                    OrderItemDO updateItem = new OrderItemDO();
                    updateItem.setId(orderItemDO.getId());
                    updateItem.setAddonAmount(addonAmount);
                    updateItem.setTotalPrice(newTotalPrice);
                    orderItemMapper.updateById(updateItem);

                    totalPrice = newTotalPrice;
                }

                totalAmount = totalAmount.add(totalPrice);
                totalQuantity += orderItemDO.getQuantity();
            }

            // 更新子订单
            OrderInfoDO updateInfo = new OrderInfoDO();
            updateInfo.setId(orderInfo.getId());
            updateInfo.setTotalAmount(totalAmount);
            updateInfo.setActualAmount(totalAmount);
            updateInfo.setTotalQuantity(totalQuantity);
            updateInfo.setDiscountAmount(BigDecimal.ZERO);
            orderInfoMapper.updateById(updateInfo);

            totalActualAmount = totalActualAmount.add(totalAmount);
            allTotalQuantity += totalQuantity;
        }

        // 更新主订单
        OrderMainDO updateMain = new OrderMainDO();
        updateMain.setId(orderMain.getId());
        updateMain.setTotalActualAmount(totalActualAmount);
        updateMain.setTotalQuantity(allTotalQuantity);
        orderMainMapper.updateById(updateMain);

        // 返回 VO（与 preview 一致）
        return buildAmountSummaryVO(totalActualAmount, allTotalQuantity);
    }

    // ==================== 公共查询与计算逻辑 ====================

    /**
     * 查询商品相关数据（只读）
     */
    private OrderCalcContext prepareOrderContext(List<OrderItemParam> orderItemList) {
        List<Long> goodsId = orderItemList.stream().map(OrderItemParam::getGoodsId).distinct().collect(Collectors.toList());

        if (goodsId.isEmpty()) {
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "商品ID列表为空");
        }

        // 查询商品
        List<ProductDO> productList = productMapper.selectBatchIds(goodsId);
        if (productList.size() != goodsId.size()) {
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "部分商品不存在");
        }
        Map<Long, ProductDO> productMapById = productList.stream().collect(Collectors.toMap(ProductDO::getId, Function.identity()));
        Map<Long, List<ProductDO>> productGroupByShop = productList.stream().collect(Collectors.groupingBy(ProductDO::getShopId));

        // 查询店铺
        List<ShopDO> shopList = shopMapper.selectBatchIds(productGroupByShop.keySet());
        Map<Long, ShopDO> shopMap = shopList.stream().collect(Collectors.toMap(ShopDO::getId, Function.identity(), (x, y) -> x));

        // 查询 SKU
        LambdaQueryWrapper<ProductSkuDO> skuWrapper = new LambdaQueryWrapper<>();
        skuWrapper.in(ProductSkuDO::getProductId, goodsId);
        List<ProductSkuDO> skuList = productSkuMapper.selectList(skuWrapper);
        Map<Long, List<ProductSkuDO>> skuMap = skuList.stream().collect(Collectors.groupingBy(ProductSkuDO::getProductId));

        // 查询附加项
        List<ProductAddonDTO> addonList = productBaseAddonRelationMapper.getProductAddon(goodsId);
        Map<Long, List<ProductAddonDTO>> addonMap = addonList.stream().collect(Collectors.groupingBy(ProductAddonDTO::getProductId));

        return new OrderCalcContext(orderItemList, productMapById, productGroupByShop, shopMap, skuMap, addonMap);
    }

    private OrderAmountSummaryVO calculateAmount(OrderCalcContext ctx) {
        BigDecimal totalActualAmount = BigDecimal.ZERO;
        int allTotalQuantity = 0;

        for (Map.Entry<Long, List<ProductDO>> entry : ctx.productGroupByShop.entrySet()) {
            Long shopId = entry.getKey();
            BigDecimal totalAmount = BigDecimal.ZERO;
            int totalQuantity = 0;

            for (ProductDO product : entry.getValue()) {
                OrderItemParam itemParam = ctx.orderItemList.stream().filter(p -> p.getGoodsId().equals(product.getId())).findFirst().orElseThrow(() -> new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "商品参数缺失: " + product.getId()));

                // 匹配 SKU
                String specJson = itemParam.getPropertyChildIds();
                List<ProductSkuDO> skus = ctx.skuMap.get(product.getId());
                if (CollectionUtils.isEmpty(skus)) {
                    throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "商品无SKU: " + product.getId());
                }

                ProductSkuDO matchedSku = skus.stream().filter(sku -> SpecJsonUtils.equalsIgnoreOrder(sku.getSpecJson(), specJson)).findFirst().orElse(skus.get(0)); // 降级取第一个

                BigDecimal unitPrice = matchedSku.getSalePrice();
                int quantity = itemParam.getNumber();
                BigDecimal subtotal = unitPrice.multiply(BigDecimal.valueOf(quantity));
                BigDecimal totalPrice = subtotal.setScale(2, RoundingMode.HALF_UP);

                // 处理附加项
                List<GoodsAdditionParam> additions = itemParam.getGoodsAdditionList();
                if (CollectionUtils.isNotEmpty(additions)) {
                    List<Long> addonValueIds = additions.stream().map(GoodsAdditionParam::getId).collect(Collectors.toList());

                    List<ProductAddonDTO> validAddons = ctx.addonMap.getOrDefault(product.getId(), Collections.emptyList()).stream().filter(dto -> addonValueIds.contains(dto.getAddonValueId())).collect(Collectors.toList());

                    if (validAddons.size() != addonValueIds.size()) {
                        throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR, "附加项无效或不属于该商品");
                    }

                    BigDecimal addonAmount = validAddons.stream().map(ProductAddonDTO::getAddonPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

                    // ⚠️ 关键：此处模仿 create() 的逻辑（即使有误）
                    // create() 中是：pricePerUnit = unitPrice + addonAmount（错误地将总附加费当单价加）
                    BigDecimal pricePerUnit = unitPrice.add(addonAmount);
                    totalPrice = pricePerUnit.multiply(BigDecimal.valueOf(quantity)).setScale(2, RoundingMode.HALF_UP);
                }

                totalAmount = totalAmount.add(totalPrice);
                totalQuantity += quantity;
            }

            totalActualAmount = totalActualAmount.add(totalAmount);
            allTotalQuantity += totalQuantity;
        }

        return buildAmountSummaryVO(totalActualAmount, allTotalQuantity);
    }

    private OrderAmountSummaryVO buildAmountSummaryVO(BigDecimal totalAmount, int totalQuantity) {
        OrderAmountSummaryVO vo = new OrderAmountSummaryVO();
        vo.setGoodsNumber(totalQuantity);
        vo.setAmountTotle(totalAmount);
        vo.setAmountTotleOriginal(totalAmount);
        vo.setAmountReal(totalAmount);
        vo.setAmountLogistics(BigDecimal.ZERO);
        vo.setAmountLogistics2(BigDecimal.ZERO);
        vo.setAmountTax(BigDecimal.ZERO);
        vo.setAmountTaxGst(BigDecimal.ZERO);
        vo.setAmountTaxService(BigDecimal.ZERO);
        vo.setCouponAmount(BigDecimal.ZERO);
        vo.setCouponId(null);
        vo.setMultilevelPriceDiscountsTotalAmount(BigDecimal.ZERO);
        vo.setCanDeductionAmountTotal(BigDecimal.ZERO);
        vo.setCanDeductionScoreTotal(0);
        vo.setDeductionMoney(BigDecimal.ZERO);
        vo.setDeductionScore(0);
        vo.setFreightScore(0);
        vo.setScore(0);
        vo.setIsNeedLogistics(true);
        vo.setOverseas(false);
        vo.setGoodsAdditionalPriceMap(null);
        return vo;
    }


    // ==================== 内部上下文类 ====================

    private static class OrderCalcContext {
        final List<OrderItemParam> orderItemList;
        final Map<Long, ProductDO> productMapById;
        final Map<Long, List<ProductDO>> productGroupByShop;
        final Map<Long, ShopDO> shopMap;
        final Map<Long, List<ProductSkuDO>> skuMap;
        final Map<Long, List<ProductAddonDTO>> addonMap;

        public OrderCalcContext(List<OrderItemParam> orderItemList, Map<Long, ProductDO> productMapById, Map<Long, List<ProductDO>> productGroupByShop, Map<Long, ShopDO> shopMap, Map<Long, List<ProductSkuDO>> skuMap, Map<Long, List<ProductAddonDTO>> addonMap) {
            this.orderItemList = orderItemList;
            this.productMapById = productMapById;
            this.productGroupByShop = productGroupByShop;
            this.shopMap = shopMap;
            this.skuMap = skuMap;
            this.addonMap = addonMap;
        }
    }
}


